In software engineering, a spinlock is a lock where a requester (e.g., a processor) waits in a loop (“spins”) and the requester repeatedly checks if it can obtain the lock while waiting in the loop. After the requester obtains the spinlock, the requester will hold the spinlock until the requester releases the spinlock. The requester is required to hold the spinlock in order to access to a shared object such as, for example, a critical section in a memory, a shared data structure, a semaphore, or other suitable shared resources.
One type of spinlock is the read-write spinlock. A read-write spinlock permits multiple readers (i.e., requesters performing reading) to access the shared object at the same time, but the read-write spinlock only permits one writer (i.e., a requester performing writing) to access the shared object at any particular time, and the readers are not permitted to read to the shared object when a writer is writing to the shared object.
Previous read-write spinlocks use a guard lock or use two guard locks (or more in some implementations, e.g. one for each processor) to guard the access of readers and writers to a shared object. For a read-write spinlock that use one guard lock, a reader or writer first obtains the guard lock before a reader can obtain the read-write spinlock for reading (or before a writer can obtain the read-write spinlock for writing). For example, a reader that is trying to obtain the guard lock is required to wait if a writer is currently holding the guard lock. Additionally, before a reader (or writer) releases the read-write spinlock, the reader (or writer) is required to first obtain the guard lock and then alter the data structure of the read-write spinlock to indicate that the reader (or writer) has released the read-write spinlock. Therefore, the read-write spinlock with one guard lock requires a requester to perform two acquisitions and two releases of the guard lock.
For a read-write spinlock that use two guard locks (“guard1” and “guard2”), a reader that is trying to obtain the read-write spinlock will first acquire guard1, then increment a reader entry count, and then will release guard1. The reader then acquires the read-write spinlock and performs a read operation on the shared object. When the reader releases the read-write spinlock, the reader will first acquire guard2, then increments a reader exit count, and then will release guard2 prior to releasing the read-write spinlock. For a writer to obtain the read-write spinlock, the reader entry count has to be equal in value to the reader exit count. One example of an operating system that uses the read-write spinlock with two guard locks is the HP-UX operating system which is commercially available from HEWLETT-PACKARD COMPANY, Palo Alto, Calif.
All of these multiple guard lock acquisitions and release steps in the above-discussed previous methods are expensive in terms of CPU time in two ways: first, the sheer number of instructions that are executed (i.e., multiple spinlock and spinunlock calls), and second, on a machine with many processors, the time spent holding the guard locks can cause processor contention, which means the CPU just spins while waiting for the guard lock to become available. A third expense is that because the guard locks are shared objects, their use often incurs cache penalties, particularly under heavy use when many processors are accessing them. Additionally, the use of two guard locks makes the read-write spinlocks larger in data structure size.
Therefore, the current technology is limited in its capabilities and suffers from at least the above constraints and deficiencies.